<?php
namespace app\Wechat;
use Server\Components\CatCache\CatCacheRpcProxy;
use Server\CoreBase\Child;
class WxAuth
{

    public $appId;

    public $appSecret;
    protected $redis;
    protected $loader;

    public function __construct($appId, $appSecret)
    {
        $this->appId = $appId;
        $this->appSecret = $appSecret;
        $this->loader = get_instance()->loader;
        $parent = new Child();
        $this->redis = $this->loader->redis("redisPool", $parent);
    }

    /**
     * 获取微信回传code值
     *
     * @param string $url:code回传到页面
     * @param string $snsapi:是否弹出微信授权页面。snsapi_userinfo：弹出，snsapi_base：不弹出
     *
     * @return code
     */
    public function getCode($url, $snsapi = 'snsapi_base')
    {
        $url = urlencode($url);
        return 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=' . $this->appId . '&redirect_uri=' . $url . '&response_type=code&scope=' . $snsapi . '&state=1&connect_redirect=1#wechat_redirect';
    }

    /**
     * 通过code获取用户基本信息
     *
     * @return array {access_token,expires_in,refresh_token,openid,scope}
     */
    public function getOAuth($code = '')
    {
        if(empty($code)){
            $code = isset($_GET['code']) ? $_GET['code'] : '';
        }

        if (! $code) {
            return false;
        }
        // GET请求连接
        $get_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" . $this->appId . "&secret=" . $this->appSecret . "&code=" . $code . "&grant_type=authorization_code";
        $result = $this->http_get($get_token_url);
        if ($result) {
            $json = json_decode($result, true);
            if (isset($json['access_token'])) {
                return $json;
            } else {
                return false;
            }
        }
        return false;
    }

    //小程序通过code 获取session_key,oepnid
    public function getSmallOAuth($code=''){
        if(empty($code)){
            $code = isset($_GET['code']) ? $_GET['code'] : '';
        }
        if (! $code) {
            return false;
        }
        // GET请求连接
        $get_token_url ="https://api.weixin.qq.com/sns/jscode2session?appid=". $this->appId ."&secret=" . $this->appSecret . "&js_code=". $code . "&grant_type=authorization_code";
        $result = $this->http_get($get_token_url);
        if ($result) {
            $json = json_decode($result, true);
            if (isset($json['openid'])) {
                return $json;
            } else {
                return false;
            }
        }
        return false;
    }

    /**
     * 获取用户详细信息
     *
     * @param string $openid:微信用户openid
     * @return mixed|boolean {
     *         "subscribe": 1,
     *         "openid": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M",
     *         "nickname": "Band",
     *         "sex": 1,
     *         "language": "zh_CN",
     *         "city": "广州",
     *         "province": "广东",
     *         "country": "中国",
     *         "headimgurl":"http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
     *         "subscribe_time": 1382694957,
     *         "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"
     *         "remark": "",
     *         "groupid": 0
     *         }
     */
    public function getWxUserInfo($openid)
    {
        $accessToken = $this->getAccessToken();
        $url = 'https://api.weixin.qq.com/cgi-bin/user/info?access_token=' . $accessToken . '&openid=' . $openid . '&lang=zh_CN';
        $result = $this->http_get($url);
        if ($result) {
            $json = json_decode($result, true);
            if ($json) {
                return $json;
            } else {
                return false;
            }
        }
    }

    public function getWxUserInfo2($openid, $accessToken)
    {
        $url = 'https://api.weixin.qq.com/sns/userinfo?access_token=' . $accessToken . '&openid=' . $openid . '&lang=zh_CN';

        $result = $this->http_get($url);
        if ($result) {
            $json = json_decode($result, true);
            if ($json) {
                return $json;
            } else {
                return false;
            }
        }
    }

    /**
     * 生成二维码
     */
    public function getLimitQRCode($scene_id)
    {
        $params = array(
            'action_name' => 'QR_LIMIT_STR_SCENE',
            'action_info' => array(
                'scene' => array(
                    'scene_str' => $scene_id
                )
            )
        );
        $accessToken = $this->getAccessToken();
        $json_str = json_encode($params);
        $result = $this->http_post('https://api.weixin.qq.com/cgi-bin/qrcode/create?' . 'access_token=' . $accessToken, $json_str);
        $ticket = json_decode($result, true);
        if (isset($ticket['ticket'])) {
            return $ticket;
        }
        exit('system error');
    }

    /**
     * 发送模板消息
     *
     * @param string $openid
     *            接受者openid
     * @param string $template_id
     *            消息模板id
     * @param array $data
     *            参数
     * @param string $url
     *            点击模板消息，跳转页面
     * @param string $topcolor
     *            模板消息背景颜色
     * @return boolean
     */
    public function sendTemplateMessage($openid, $template_id, $data, $url = '', $topcolor = '#FF0000')
    {
        $params = array(
            'touser' => $openid,
            'template_id' => $template_id,
            'url' => $url,
            'topcolor' => $topcolor,
            'data' => $data
        );
        $accessToken = $this->getAccessToken();
        $json_str = json_encode($params);
        $result = $this->http_post('https://api.weixin.qq.com/cgi-bin/message/template/send?' . 'access_token=' . $accessToken, $json_str);
        $message = json_decode($result, true);
       
        if ($message['errcode'] == 0) {
            return true;
        }
        return false;
    }

     /**
     *
     * @param string $openid
     * @param string $template_id
     * @param array $data
     * @param string $page
     * @param string $topcolor 模板消息背景颜色
     * @return boolean
     */
    /**
     *    小程序发送模板消息
     * @param $openid   接受者openid
     * @param $template_id   消息模板id
     * @param $form_id
     * @param $data        参数
     * @param string $page   点击模板消息，跳转页面
     * @param string $color
     * @param string $emphasis_keyword
     * @param string $name
     * @return bool
     */
    function sendSmallTemplateMessage($openid,$template_id,$form_id,$data,$page='',$color='#000000',$emphasis_keyword='',$name='user'){
        var_dump("开始发送模板消息");
        $params=array(
            'touser'=>$openid,
            'template_id'=>$template_id,
            'form_id'=>$form_id,
            'page'=>$page,
            'color'=>$color,
            'data'=>$data,
            'emphasis_keyword'=>$emphasis_keyword
        );
        $accessToken=$this->getAccessToken($name);
        $json_str=json_encode($params);
        $result=$this->http_post('https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token='.$accessToken,$json_str);
        $message=json_decode($result,true);
        if($message['errcode']==0){
            return true;
        }
        return false;
    }
    /**
     * 小程序-下发小程序和公众号统一的服务消息
     * @param type $openid  小程序openid
     * @param type $weapp_template_msg 小程序模板消息相关的信息,具体见小程序文档
     * @param type $mp_template_msg 公众号模板消息相关的信息 具体见小程序文档
     * @param type $name
     * @return boolean
     */
    function smallSendUniformMessage($openid,$weapp_template_msg,$mp_template_msg='',$name='user'){
        $accessToken=$this->getAccessToken($name);//小程序的access_token
        $params = array(
            'touser'=>$openid,
            'weapp_template_msg'=>$weapp_template_msg,
            'mp_template_msg'=>$mp_template_msg
        );
        $json_str=json_encode($params);
        $result=$this->http_post('https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token='.$accessToken,$json_str);
        $message=json_decode($result,true);
        if($message['errcode']==0){
            return true;
        }
        return false;
    }


    // 小程序--图片--安全检测
    function imgSecCheck($image, $name='user')
    {
        // 1-- 获取token
        $accessToken = $this->getAccessToken($name);
        $url = 'https://api.weixin.qq.com/wxa/img_sec_check?access_token='.$accessToken;
        $image_info = getimagesize($image);
        $cfile = curl_file_create($image,$image_info['mime'], '@testpic'); //这里硬编码了,自己修改
        $params = array('media' => $cfile);
        $data = json_encode($params, JSON_UNESCAPED_UNICODE);
        $res = $this->http_post($url, $data,true,array('Content-Type:application/octet-stream'));
        $res=json_decode($res,true);
        return $res;
    }
     // 小程序--文字--安全检测
    function imgMsfCheck($content, $name='user')
    {
        // 1-- 获取token
       $accessToken = $this->getAccessToken($name);
       $url = 'https://api.weixin.qq.com/wxa/msg_sec_check?access_token='.$accessToken;
       // '完2347全dfji试3726测asad感3847知qwez到'
        $params=array(
            'content' =>$content
        );
        $data = json_encode($params, JSON_UNESCAPED_UNICODE);
        $res = $this->http_post($url, $data);
        $res=json_decode($res,true);
        return $res;
    }

    public function wxCustomMenu($json_str)
    {
        $accessToken = $this->getAccessToken();
        $result = $this->http_post('https://api.weixin.qq.com/cgi-bin/menu/create?access_token=' . $accessToken, $json_str);
        $ticket = json_decode($result, true);
        return $ticket;
    }

    /**
     * 获取微信JS-SDK 配置信息
     *
     * @return multitype:string number unknown NULL
     */
    public function getSignPackage($url = '')
    {
        $jsapiTicket = $this->getJsApiTicket();


        // 注意 URL 一定要动态获取，不能 hardcode.
        if (! $url) {
            $protocol = (! empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
            $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
        }

        $timestamp = time();
        $nonceStr = $this->createNonceStr();


        // 这里参数的顺序要按照 key 值 ASCII 码升序排序
        $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";

        $signature = sha1($string);

        $signPackage = array(
            "appId" => $this->appId,
            "nonceStr" => $nonceStr,
            "timestamp" => $timestamp,
            "signature" => $signature,
            "url" => $url
        );

        return $signPackage;
    }

    /**
     * 获取getaddrSign
     *
     * @return multitype:string number unknown NULL
     */
    public function getaddrSign($url, $token)
    {
        $timestamp = strval(time());
        $nonceStr = $this->createNonceStr();

        $obj['appid'] = $this->appId;
        $obj['accesstoken'] = $token;
        $obj['timestamp'] = $timestamp;
        $obj['noncestr'] = $nonceStr;
        $obj['url'] = $url;

         //参数小写
        foreach ($obj as $k => $v){
            $bizParameters[strtolower($k)] = $v;
        }
        //字典序排序
        ksort($bizParameters);
        //URL键值对拼成字符串
        $buff = "";
        foreach ($bizParameters as $k => $v){
            $buff .= $k."=".$v."&";
        }
        //去掉最后一个多余的&
        $buff2 = substr($buff, 0, strlen($buff) - 1);
        //sha1签名
        $addrSign = sha1($buff2);

        $signPackage = array(
            "appId" => $this->appId,
            "nonceStr" => $nonceStr,
            "timestamp" => $timestamp,
            "addrSign" => $addrSign
        );
        return $signPackage;
    }

    /**
     * 获取AccessToken
     *
     * @return boolean|unknown
     */
    public function getAccessToken($name='user')
    {
       
        //设置缓存
       // CatCacheRpcProxy::getRpc()->offsetSet('188','212');
       // 读取缓存
       //$t = CatCacheRpcProxy::getRpc()->offsetGet('188');
       //$atoken = json_decode(CatCacheRpcProxy::getRpc()->offsetGet('accesstoken_'.$name),true);
        $atoken = json_decode($this->redis->get('accesstoken_'.$name),true);
       if (empty($atoken)||$atoken['expire']<time()) {
            // GET请求连接
            $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $this->appId . '&secret=' . $this->appSecret;
            $result = $this->http_get($url);
            // 判断是否获取access_token
            if ($result) {
                $json = json_decode($result, true);
                $AccessToken = $json['access_token'];
                $arr['token'] = $AccessToken;
                $arr['expire'] = time()+4800;
                if ($AccessToken) {
                    $this->redis->set('accesstoken_'.$name, json_encode($arr));
                   // CatCacheRpcProxy::getRpc()->offsetSet('accesstoken_'.$name, json_encode($arr));
                   return $AccessToken;
                } else {
                    return false;
                }
            }
       }else{
            return $atoken['token'];
        }

    }

    /**
     * 获取微信JS-SDK ticket
     *
     * @return boolean|unknown
     */
    public function getJsApiTicket()
    {
        // 读取缓存
        $jsapi_ticket = cache("jsapi_ticket");

        if (empty($jsapi_ticket)) {
            // GET请求连接
            $accessToken = $this->getAccessToken();
            $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";
            $result = $this->http_get($url);
            // 判断是否获取access_token
            if ($result) {
                $json = json_decode($result, true);
                $JsApiTicket = $json['ticket'];
                if ($JsApiTicket) {
                    cache("jsapi_ticket",$JsApiTicket,7200);
                   return $JsApiTicket;
                } else {
                    return false;
                }
            }
        }else{
            return $jsapi_ticket;
        }

    }

     /**
     * 获取微信JS-SDK ticket
     *
     * @return boolean|unknown
     */
    public function getCardJsApiTicket()
    {
        // 读取缓存
        $jsapi_ticket = cache("jsapi_ticket");

        if (empty($jsapi_ticket)) {
            // GET请求连接
            $accessToken = $this->getAccessToken();
            $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=wx_card&access_token=$accessToken";
            $result = $this->http_get($url);
            // 判断是否获取access_token
            if ($result) {
                $json = json_decode($result, true);
                $JsApiTicket = $json['ticket'];
                if ($JsApiTicket) {
                    cache("jsapi_ticket",$JsApiTicket,7200);
                   return $JsApiTicket;
                } else {
                    return false;
                }
            }
        }else{
            return $jsapi_ticket;
        }

    }

    /**
     * 随机字符串
     *
     * @param number $length
     * @return string
     */
    public function createNonceStr($length = 16)
    {
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i ++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    /**
     * 卡券code解码
     * @Author   lcx
     * @DateTime 2017-11-20
     * @desc     {string}
     * @param               {string}
     * @param    [type]     $openid      [description]
     * @param    [type]     $accessToken [description]
     * @return   [type]                  [description]
     */
    public function decrytCardCode($encrypt_code,$card_id)
    {

        $accessToken = $this->getAccessToken();
        $json_str = "{'encrypt_code':$encrypt_code,'card_id':$card_id}";

        $result = $this->http_post("https://api.weixin.qq.com/card/code/decrypt?access_token=$accessToken", $json_str,true);

        if ($result) {
            $json = json_decode($result, true);
            if ($json) {
                return $json;
            } else {
                return false;
            }
        }
    }

    /**
     * GET 请求
     *
     * @param string $url
     */
    private function http_get($url)
    {
        $oCurl = curl_init();
        if (stripos($url, "https://") !== FALSE) {
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, FALSE);
            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); // CURL_SSLVERSION_TLSv1
        }
        curl_setopt($oCurl, CURLOPT_URL, $url);
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1);
        $sContent = curl_exec($oCurl);
        $aStatus = curl_getinfo($oCurl);
        curl_close($oCurl);
        if (intval($aStatus["http_code"]) == 200) {
            return $sContent;
        } else {
            return false;
        }
    }

    /**
     * POST 请求
     *
     * @param string $url
     * @param array $param
     * @param boolean $post_file
     *            是否文件上传
     * @return string content
     */
    public function http_post($url, $param, $post_file = false,$headers="")
    {
        $oCurl = curl_init();
        if (stripos($url, "https://") !== FALSE) {
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); // CURL_SSLVERSION_TLSv1
        }
        if (is_string($param) || $post_file) {
            $strPOST = $param;
        } else {
            $aPOST = array();
            foreach ($param as $key => $val) {
                $aPOST[] = $key . "=" . urlencode($val);
            }
            $strPOST = join("&", $aPOST);
        }
        curl_setopt($oCurl, CURLOPT_URL, $url);
        curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($oCurl, CURLOPT_POST, true);
        curl_setopt($oCurl, CURLOPT_POSTFIELDS, $strPOST);
        if(!empty($headers)){
             curl_setopt($oCurl, CURLOPT_HTTPHEADER, $headers);
        }
       
        $sContent = curl_exec($oCurl);
        $aStatus = curl_getinfo($oCurl);
        curl_close($oCurl);
        if (intval($aStatus["http_code"]) == 200) {
            return $sContent;
        } else {
            return false;
        }
    }

    public function isSubscribe($openid){
        $access_token= $this->getAccessToken();
        $subscribe_msg = 'https://api.weixin.qq.com/cgi-bin/user/info?access_token='.$access_token.'&openid='.$openid;
        $subscribe = json_decode($this->http_get($subscribe_msg));
        $res = $subscribe->subscribe;
        return $res;
    }
    
    //小程序生成二维码
    public function getSamllPageQr($scene,$width,$auto_color=false,$line_color="{'r':'0','g':'0','b':'0'}",$page=''){
        $accesstoken = $this->getAccessToken('user');
        $url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=".$accesstoken;
        
         if(!empty($scene)){
            $params['scene'] = $scene;
        }
        $params['width'] = $width;
        if(!empty($page)){
            $params['page'] = $page;
        }
       $json_str = json_encode($params);
        $result = $this->http_post($url,$json_str);
        if ($result) {
            return $result;
        }
        return false;
    }

}